use crate::pool;
use rbatis::{crud, impl_delete, impl_select, impl_select_page, Page, rbdc::{self, db::ExecResult}, sql::{self, PageRequest}};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TbDevice {
    pub id: String,
    pub appid: Option<String>,
    pub device_id: Option<String>,
    pub sn: Option<String>,
    pub ip: Option<String>,
    pub mac: Option<String>,
    pub enabled: Option<u32>,
    pub status: Option<u32>,
    pub custom_data: Option<String>,
}

crud!(TbDevice {});
impl_select!(TbDevice {select(appid: &pilota::FastStr, device_ids: &Vec<pilota::FastStr>) =>
    "`where 1=1`
    if appid!='' && device_ids.len>0:
        if device_ids.len==1:
            ` and id=#{appid+':'+device_ids[0]}`
        if device_ids.len>1:
            ` and appid=#{appid} and device_id in #{device_ids}`
    if device_ids.len==0:
        ` and appid=#{appid}`"
});
impl_select_page!(TbDevice {select_page() => ""});
impl_delete!(TbDevice {delete(appid: &pilota::FastStr, device_ids: &Vec<pilota::FastStr>) =>
    "`where 1=1`
    if appid!='':
        ` and appid=#{appid}`
    if device_ids.len>0:
        ` and device_id in #{device_ids}`"
});

impl TbDevice {
    pub async fn get_devices(
        page: &crate::common::QueryPage,
    ) -> Result<Page<TbDevice>, rbdc::Error> {
        TbDevice::select_page(pool!(), &PageRequest::from(page)).await
    }

    pub async fn update_device(data: &TbDevice) -> Result<ExecResult, rbdc::Error> {
        TbDevice::update_by_column(pool!(), data, "id").await
    }

    pub async fn delete_device(
        data: &crate::handlers::device::Delete,
    ) -> Result<ExecResult, rbdc::Error> {
        TbDevice::delete_by_column(pool!(), "id", &data.id).await
    }

    pub async fn query_devices(
        appid: &pilota::FastStr,
        device_ids: &Vec<pilota::FastStr>,
    ) -> Result<Vec<TbDevice>, rbdc::Error> {
        TbDevice::select(pool!(), appid, device_ids).await
    }

    pub async fn insert_device(data: &TbDevice) -> Result<ExecResult, rbdc::Error> {
        TbDevice::insert(pool!(), data).await
    }

    pub async fn delete_devices_by_appid_and_deviceids(
        appid: &pilota::FastStr,
        device_ids: &Vec<pilota::FastStr>,
    ) -> Result<ExecResult, rbdc::Error> {
        TbDevice::delete(pool!(), appid, device_ids).await
    }
}
